﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CmdDrawSlopeLine.h"
#include "CmdStatusUtils.h"
#include "ActionDrawStraightElementInput.h"
#include "ActionDrawStraightElementCreator.h"
#include "UIProfileSlopeEditModeBehaviorBase.h"
#include "UiEditModeUtils.h"
#include "IGraphicsNodeGroup.h"
#include "IPlane.h"
#include "Vector2dUtils.h"
#include "IModelView.h"
#include "IStructureSlopeLine.h"
#include "GbmpGraphicsNodeUtils.h"
#include "IDocument.h"
#include "GmUiStructureCommandRegister.h"
#include "IUserTransaction.h"
#include "GbmpPresetParameterUIUtils.h"
#include "IMainWindow.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

//////////////////////////////////////////////////////////////////
//CmdDrawSlopeline

REGISTER_GM_COMMAND(CmdDrawSlopeline)

CmdDrawSlopeline::CmdDrawSlopeline(const std::wstring& cmdId)
    : GbmpCommandBase(cmdId)
{

}

bool CmdDrawSlopeline::IsEnabled() const
{
    //// 只要有一个坡度线可见，则此命令不可用
    //std::vector<IElement*> allSlopeElements = gcmp::GbmpDocUtils::GetElementsByCategory(UiDocumentViewUtils::GetCurrentDocument(), BuiltInCategoryUniIdentities::BICU_STRUCTURE_FLOOR_SLOPELINE);
    //FOR_EACH(pElem, allSlopeElements)
    //{
    //    if (IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElem))
    //    {
    //        if (StructureSlopeLine* pSlope = quick_cast<StructureSlopeLine>(pGenericElement->GetExternalObject()))
    //        {
    //            if (pSlope->IsVisible())
    //            {
    //                return false;
    //            }
    //        }
    //    }
    //}

    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT
}

bool CmdDrawSlopeline::IsVisible() const
{
    CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT
}

OwnerPtr<IAction> CmdDrawSlopeline::ExecuteCommand(const CommandParameters& cmdParams)
{
    IUiDocument* pUIDoc = UiDocumentViewUtils::GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUIDoc, L"pUIDoc指针无效",L"GDMPLab",L"2024-03-30");

    ActionDrawStraightElementInput actionInput;
    actionInput.CommandId = GetCommandId();
    actionInput.DrawLineMode = DrawLineMode::Only_One;
    actionInput.PreviewLineEnabled = false;
    actionInput.LineUpdateCallback = ActionDrawStraightElementInput::CreateOnLineUpdateCallback(&CmdDrawSlopeline::OnLineUpdate, this);
    actionInput.LineFinishedCallback = ActionDrawStraightElementInput::CreateOnLineFinishedCallback(
        &CmdDrawSlopeline::OnLineFinished, this);
    actionInput.ActionDestroyCallback = ActionDrawStraightElementInput::CreateOnActionDestroyCallback(
        &CmdDrawSlopeline::OnActionDestroy, this);

    OwnerPtr<IAction> opAction = ActionDrawStraightElementCreator::Create(actionInput);

    UIProfileSlopeEditModeBehaviorBase* pUIProfileEditModeBehavior = dynamic_cast<UIProfileSlopeEditModeBehaviorBase*>(UiEditModeUtils::GetCurrentUiEditModeBehavior(pUIDoc));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pUIProfileEditModeBehavior, L"pUIProfileEditModeBehavior为空",L"GDMPLab",L"2024-03-30");

    pUIProfileEditModeBehavior->SetIsDrawingSlopeLine(true);
    //更新文档
    UiEditModeUtils::RefreshEditModeUi(pUIDoc);

    return TransferOwnership(opAction);
}

OwnerPtr<IGraphicsNodeGroup> CmdDrawSlopeline::OnLineUpdate(
    IUiView* pCurrentView, const Vector3d& startPt, const Vector3d& endPt)
{
    OwnerPtr<IGraphicsNodeGroup> opRet = IGraphicsNodeGroup::Create();
    DBG_WARN_AND_RETURN_UNLESS(opRet, opRet, L"opRet为空",L"GDMPLab",L"2024-03-30");

    DBG_WARN_AND_RETURN_UNLESS(pCurrentView, opRet, L"pCurrentView为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, opRet, L"无效的文档",L"GDMPLab",L"2024-03-30");
    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_UNLESS(pModelView, opRet, L"pModelView为空",L"GDMPLab",L"2024-03-30");
    OwnerPtr<IPlane> opWorkPlane = pModelView->GetWorkPlane();
    DBG_WARN_AND_RETURN_UNLESS(opWorkPlane, opRet, L"opWorkPlane为空",L"GDMPLab",L"2024-03-30");

    if (Vector2dUtils::IsEqual(startPt.Vec2d(), endPt.Vec2d()))
    {
        return opRet;
    }

    // 创建预览坡度线
    IStructureSlopeLine* pSlope = IStructureSlopeLine::Create(pDoc, startPt, endPt, ElementCreationOptions::Transient);
    DBG_WARN_AND_RETURN_UNLESS(pSlope, opRet, L"pSlope为空",L"GDMPLab",L"2024-03-30");

    // 生成临时预览坡度线的ElementShape
    opRet = GbmpGraphicsNodeUtils::TransferGRepToGGroup(pSlope->GetGraphicsLineAndArrow());
    opRet->SetIsSnappable(false);

    // 删除临时预览对象
    pDoc->DeleteElement(pSlope->GetOwnerElement()->GetElementId());

    return opRet;
}

ElementId CmdDrawSlopeline::OnLineFinished(IUiView* pCurrentView,
    const Vector3d& startPt, const Vector3d& endPt,
    const ISnap* pStartSnap, const ISnap* pEndSnap)
{
    DBG_WARN_AND_RETURN_UNLESS(pCurrentView != nullptr, ElementId::InvalidID, L"当前视图为空",L"GDMPLab",L"2024-03-30");
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_UNLESS(pDoc, ElementId::InvalidID, L"pFamily指针无效",L"GDMPLab",L"2024-03-30");

    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(pDoc, GBMP_TR(L"绘制楼板坡度线"));
    IStructureSlopeLine* pSlopeline = IStructureSlopeLine::Create(pDoc, startPt, endPt);

    ut->Commit();

    ElementId ownerId = pSlopeline && pSlopeline->GetOwnerElement() ? pSlopeline->GetOwnerElement()->GetElementId() : ElementId::InvalidID;
    return ownerId;
}

void CmdDrawSlopeline::OnActionDestroy()
{
    GbmpPresetParameterUIUtils::UpdatePropertyPanel(ElementId::InvalidID);
    GbmpPresetParameterUIUtils::EnablePropertyPanel(true);

    IMainWindow* pMainWnd = IMainWindow::GetMainWindow();
    if (pMainWnd)
    {
        pMainWnd->UpdateControlStatus();
    }
}
